package ar.uba.dc.sistemas.monitorRW;

/**
 * 
 * Esta implementacion da preferencia a los escritores.
 * Un lector no puede comenzar a leer si hay un escritor escribiendo o esperando para escribir, 
 * en caso de no ser asi puede comenzar inmediatamente.
 * Un escritor no puede comenzar a escribir si hay algun lector leyendo o si hay otro escritor escribiendo.
 *
 * @author Hernan Berroja Albiz / German del Tuffo
 * @version 0.1
 */

public class WritersPreferred implements MultipleReadersWritersMonitor {
    /**
     * cantidad de lectores leyendo
     */
    protected int cantidadLectores = 0;
    /**
     * cantidad Total de lectores(leyendo o esperando para leer)
     */
    protected int cantTotalLectores = 0;
    /**
     * cantidad de Escritores escribiendo, pueden ser 0 o 1
     */
    protected int cantidadEscritores = 0;
    /**
     * cantidad de escritores totales (escribiendo o esperando para escribir)
     */
    protected int cantEscritoresTotal = 0;

    /**
     * Resetea el monitor.
     */
    public void reset() {
        cantidadLectores = 0;
        cantTotalLectores = 0;
        cantidadEscritores = 0;
        cantEscritoresTotal = 0;
    }

    /**
     * Este metodo es llamado para leer el objeto compartido
     *
     * 
     */
    public synchronized void comenzarLectura()
            throws InterruptedException {
        cantTotalLectores++;
        while (cantEscritoresTotal != 0) wait();
        cantidadLectores++;
    }

    /**
     * Este metodo se llama cuando se termina de leer el objeto compartido
     */
    public synchronized void detenerLectura() {
        cantidadLectores--;
        cantTotalLectores--;
        if (cantidadLectores == 0) notifyAll();
    }

    /**
     * Este metodo es llamado para escribir en el objeto compartido
     */
    public synchronized void comenzarEscritura()
            throws InterruptedException {
        cantEscritoresTotal++;
        while (cantidadLectores + cantidadEscritores != 0) wait();
        cantidadEscritores = 1;
    }

    /**
     * Este metodo es llamado cuando se termina de escribir en el objeto compartido
     */
    public synchronized void detenerEscritura() {
        cantidadEscritores = 0;
        cantEscritoresTotal--;
        notifyAll();
    }

    /**
     * Este metodo brinda informacion acerca del monitor.
     *
     * @return "Writers-Preferred Monitor"
     */
    public String getMonitorInfo() {
        return "Writers-Preferred Monitor";
    }
}

